#include "widget.h"
#include "ui_widget.h"

#include <QMouseEvent>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QtGlobal>
#include <QDir>
#include <QDebug>
//调用WIN API需要用到的头文件与库 [实现缩放]
#ifdef Q_OS_WIN
#include <qt_windows.h>
#include <Windowsx.h>
#endif
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setAcceptDrops(true); //接收拖拽文件
    ui->textEdit->setAcceptDrops(false);//禁止文本编辑框接受拖拽
    setWindowFlags(Qt::FramelessWindowHint);//隐藏标题栏
    //setAttribute(Qt::WA_TranslucentBackground, true);//背景透明
    ui->btn_return->setVisible(false);    //隐藏 返回按钮
    showBackUpMdxCount();//显示备份文件数量

    //捕获事件过滤器
    ui->titilelWidget->installEventFilter(this);
    ui->label_help->installEventFilter(this);
    ui->label_close->installEventFilter(this);
    ui->label_jz->installEventFilter(this);


    m_nBorderWidth = 5;//缩放窗口边框宽度
    //设置捐助图片
    QPixmap pixmapWxzf(":/pic/wx.png");
    QPixmap pixmapZfbzf(":/pic/zfb.png");
    ui->label_wx->setPixmap(pixmapWxzf);
    ui->label_wx->show();
    ui->label_zfb->setPixmap(pixmapZfbzf);
    ui->label_zfb->show();
    ui->label_wx->setVisible(false);
    ui->label_zfb->setVisible(false);

    ui->textBrowser->setVisible(false);//隐藏帮助控件
    ui->btn_return->setVisible(false);

    //设置提示
    ui->textEdit->setText("请查看帮助之后.了解之后,将mdx文件拖进来即可.");
}

Widget::~Widget()
{
    delete ui;
    m_file.squeeze();
    m_file.clear();
}

//nativeEvent主要用于进程间通信-消息传递，使用这种方式后来实现窗体的缩放 [加上了这函数，窗口也能移动了]
bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType)

    MSG *param = static_cast<MSG *>(message);

    switch (param->message)
    {
        case WM_NCHITTEST:
        {
            int nX = GET_X_LPARAM(param->lParam) - this->geometry().x();
            int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y();

            // 如果鼠标位于子控件上，则不进行处理
            if (childAt(nX, nY) != nullptr)
                return QWidget::nativeEvent(eventType, message, result);

            *result = HTCAPTION;

            // 鼠标区域位于窗体边框，进行缩放
            if ((nX > 0) && (nX < m_nBorderWidth))
                *result = HTLEFT;

            if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()))
                *result = HTRIGHT;

            if ((nY > 0) && (nY < m_nBorderWidth))
                *result = HTTOP;

            if ((nY > this->height() - m_nBorderWidth) && (nY < this->height()))
                *result = HTBOTTOM;

            if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0)
                    && (nY < m_nBorderWidth))
                *result = HTTOPLEFT;

            if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
                    && (nY > 0) && (nY < m_nBorderWidth))
                *result = HTTOPRIGHT;

            if ((nX > 0) && (nX < m_nBorderWidth)
                    && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
                *result = HTBOTTOMLEFT;

            if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
                    && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
                *result = HTBOTTOMRIGHT;

            return true;
        }
    }

    return QWidget::nativeEvent(eventType, message, result);
}

void Widget::dragEnterEvent(QDragEnterEvent *event)
{
    // 判断拖拽文件类型，文件名 接收该动作
    if (event->mimeData()->hasFormat("text/uri-list"))
        event->acceptProposedAction();
}

// 拖拽释放处理函数
void Widget::dropEvent(QDropEvent *event)
{
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty()) return;
    int max = urls.count();
    for(int i=0;i< max;i++)
    {
        QString fileName = urls.at(i).toLocalFile();
        if (fileName.isEmpty()) return;
        myStruct m;
        m.blp = getBlp(fileName);
        if(!m.blp.isEmpty() && !isLoad(fileName))
        {

            m.filePath = fileName;
            m.item = new QListWidgetItem (fileName);
            ui->listWidget->addItem(m.item);
            m_curChooseItem = m.item;
            QFileInfo fileInfo = QFileInfo(fileName);
            ui->label_Mdx->setText(fileInfo.fileName());
            m_file << m;
            showBlp(m);
        }
    }


}

bool Widget::eventFilter(QObject * watched, QEvent * event)
{

    if (watched == ui->titilelWidget && event->type() == QEvent::MouseButtonPress) m_clickedTitle = true;
    if (watched == ui->titilelWidget && event->type() == QEvent::MouseButtonRelease) m_clickedTitle = false;

    if (watched == ui->label_help && event->type() == QEvent::MouseButtonPress) label_help_clicked();
    if (watched == ui->label_close && event->type() == QEvent::MouseButtonPress) this->close();
    if (watched == ui->label_jz && event->type() == QEvent::MouseButtonPress)
    {
        ui->label_wx->setVisible(true);
        ui->label_zfb->setVisible(true);
        ui->btn_return->setVisible(true);
        ui->listWidget->setVisible(true);

        ui->textEdit->setVisible(false);
        ui->btn_save->setVisible(false);
    }
    return QWidget::eventFilter(watched, event);
}
//移动窗口操作
void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        //获得鼠标的初始位置
        m_mouseStartPoint = event->globalPos();
        //获得窗口的初始位置
        m_windowTopLeftPoint = this->frameGeometry().topLeft();
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_clickedTitle) return;

    if(event->buttons() & Qt::LeftButton)
    {
        //获得鼠标移动的距离
        QPoint distance = event->globalPos() - m_mouseStartPoint;
        //改变窗口的位置
        this->move(m_windowTopLeftPoint + distance);
    }
}

void Widget::on_btn_exit_clicked()
{
    close();
}


QStringList Widget::getBlp(QString mdxPath)
{
    QStringList ret;
    QFile file(mdxPath);
    if(!file.open(QIODevice::ReadOnly))
    {
        ui->label_tips->setText("打开模型文件失败");
         return ret;
    }
    QByteArray data = file.readAll();
    QByteArray TEXS = "TEXS";
    int pos = data.indexOf(TEXS);
    if (pos == -1)
    {
        ui->label_tips->setText("该模型没有贴图");
        file.close();
        return ret;
    }
    QRegExp reg(".*\\.(blp|tga)",Qt::CaseInsensitive);
    QString str;
    int k =0;
    while(k<data.size())
    {
        if(data.at(k) != '\0')
            str+= data.at(k);
        else
        {
            if(!str.isEmpty())
            {
                if(str.contains("GEOS",Qt::CaseInsensitive))
                    break;
                if(str.contains(".blp",Qt::CaseInsensitive)||str.contains(".tga",Qt::CaseInsensitive))
                {
                    ret << str;
                }
                str.clear();
            }
        }
        k++;
    }
    ui->label_tips->setText("读取成功!");
    file.close();
    return ret;

}


bool Widget::isLoad(QString mdxPath)
{
    for(int i = 0;i<m_file.count();i++)
    {
        if (mdxPath == m_file.at(i).filePath)
            return true;
    }
    return false;
}

void Widget::showBlp(myStruct m)
{
    ui->textEdit->clear();
    if(!m.blp.isEmpty())
        for(int i=0;i<m.blp.count();i++) ui->textEdit->append(m.blp.at(i));

}

void Widget::on_listWidget_itemClicked(QListWidgetItem *item)
{
    if(m_file.isEmpty()) return;
    for(int i=0;i<m_file.count();i++)
    {
        if(item == m_file.at(i).item)
        {
            showBlp(m_file.at(i));
            m_curChooseItem = m_file.at(i).item;
            QFileInfo fileInfo(m_file.at(i).filePath);
            QString name = fileInfo.fileName();
            ui->label_Mdx->setText(name);
            return;
        }
    }
}


bool Widget::on_btn_save_clicked()
{
    if(m_curChooseItem==NULL) return false;
    //读取模型路径并检测输入贴图数量
    QString mdxPath;
    QString text = ui->textEdit->toPlainText();
    QStringList row_list = text.split("\n");
    if(row_list.isEmpty()) {ui->label_tips->setText("保存失败!输入贴图数量错误."); return false;}
    if(m_file.isEmpty()) return false;
    myStruct *m;
    for(int i=0;i<m_file.count();i++)
    {
        if(m_curChooseItem == m_file.at(i).item)
        {
            mdxPath = m_file.at(i).filePath;
            m = &m_file[i];
            if(m_file.at(i).blp.count() != row_list.count())
            {
                ui->label_tips->setText("保存失败!输入贴图数量错误.");
                return false;
            }
            break;
        }
    }

    //读取文件
    QFile file(mdxPath);
    if(!file.open(QIODevice::ReadOnly))
    {
        ui->label_tips->setText("保存失败!打开模型文件失败");
         return false;
    }
    QByteArray data = file.readAll();
    file.close();

    QByteArray TEXS = "TEXS";
    int pos = data.indexOf(TEXS);
    if (pos == -1)
    {
        ui->label_tips->setText("保存失败!该模型没有贴图");
        file.close();
        return false;
    }
    QStringList newBlp;
    QStringList curBlp;
    QVector<int> blpPos;
    QRegExp reg(".*\\.(blp|tga)",Qt::CaseInsensitive);
    QString str;
    int k =0;
    while(k<data.size())
    {
        if(data.at(k) != '\0')
            str+= data.at(k);
        else
        {
            if(!str.isEmpty())
            {
                if(str.contains("GEOS",Qt::CaseInsensitive))
                    break;
                if(str.contains(".blp",Qt::CaseInsensitive)||str.contains(".tga",Qt::CaseInsensitive))
                {
                    curBlp << str;
                    blpPos << k-str.length();
                }
                str.clear();
            }
        }
        k++;
    }
    //写入新数据
    for (int i=0;i<curBlp.count() ;i++ ) {
        memset(data.data()+blpPos.at(i),0,curBlp.at(i).toLocal8Bit().size());
        QString write_str = row_list.at(i);
        memcpy(data.data()+blpPos.at(i),write_str.toLocal8Bit(),write_str.toLocal8Bit().size());
        newBlp << write_str;
    }
    if(m->isBackUp)
    {
        file.open(QIODevice::Truncate|QIODevice::WriteOnly);
        file.write(data);
        ui->label_tips->setText("保存成功!");
        file.close();
        return true;
    }
    else
    {
        if(backMdx(m->filePath))
        {
            m->blp= newBlp;
            file.open(QIODevice::Truncate|QIODevice::WriteOnly);
            file.write(data);
            ui->label_tips->setText("保存成功!");
            file.close();
            m->isBackUp = true;
            return true;
        }
    }
    //ui->label_tips->setText("未知原因,保存失败!");
    return false;
}

bool Widget::backMdx(QString mdxPath)
{
    QString EditMdxPathExePath = QCoreApplication::applicationDirPath();
    QString backDir = EditMdxPathExePath+"/EditMdxPathBack";
    QDir dir;
    if (!dir.exists(backDir))
    {
        if(!dir.mkpath(backDir))
        {
            ui->label_tips->setText("新建备份目录失败!");
            return false;
        }
    }
    mdxPath.replace("\\","/");
    QFileInfo fileInfo(mdxPath);
    QString name = fileInfo.fileName();
    QString newFilePath = backDir+"/"+name;
    QFile newFile(newFilePath);
    if(newFile.exists()) newFile.remove();//如果存在备份文件则删除备份文件
    if(QFile::copy(mdxPath,newFilePath))  //将文件复制到新的文件路径下
        return true;
    else
    {
        ui->label_tips->setText("备份模型失败!");
        return false;
    }
}

void Widget::showBackUpMdxCount()
{
    QString EditMdxPathExePath = QCoreApplication::applicationDirPath();
    QString backDir = EditMdxPathExePath+"/EditMdxPathBack";
    QDir dir(backDir);
    if (!dir.exists())
    {
        ui->label_tips->setText("没有备份文件!");
        return;
    }

    QStringList files = dir.entryList(QDir::Files);
    if(files.count() > 20)
        ui->label_tips->setText(QString("备份文件数量: %1,请自行清理备份文件节约磁盘空间.").arg(files.count()));
    else
        ui->label_tips->setText(QString("备份文件数量: %1").arg(files.count()));
}





void Widget::label_help_clicked()
{
QString helpInfo ="\n\
本软件作为免费产品,因使用本软件而引发的各种问题,软件开发者概不负责.\n\n\
注意事项:\n\
    1.重要模型,为了绝对安全请自己先手工备份一次.\n\
    2.软件只在首次修改模型贴图的时候备份一次未修改之前的模型.\n\
    3.备份文件在程序所在目录下的EditMdxPathBack目录中.\n\
    4.支持同时拖入多个模型.\n\
    5.只对拖入文件做了简单判断,没事不要拖入非mdx文件.\n\
    6.修改贴图路径时保持编辑框中原有行数、格式.\n\n\
如果修改贴图路径后导致模型无法使用,请与我联系反馈Bug.\n\n\
如果觉得该软件为你带了方便,想捐助一下作者,可以点击标题栏中的￥按钮,向我捐助吧.\n\
ps:作者已经快饿死了.\n\
    作者:冰叶伤痕     Q:124070027";
    ui->textBrowser->setText(helpInfo);
    ui->textBrowser->setVisible(true);
    ui->btn_return->setVisible(true);
    ui->textEdit->setVisible(false);
    ui->listWidget->setVisible(false);
    ui->btn_save->setVisible(false);
}



void Widget::on_btn_return_clicked()
{
    ui->label_wx->setVisible(false);
    ui->label_zfb->setVisible(false);
    ui->textBrowser->setVisible(false);
    ui->btn_return->setVisible(false);
    ui->textEdit->setVisible(true);
    ui->listWidget->setVisible(true);
    ui->btn_save->setVisible(true);

}

